//
//  KLQRCodeViewController.swift
//  BCWeiBo
//
//  Created by bcmac3 on 16/3/31.
//  Copyright © 2016年 KellenYangs. All rights reserved.
//

import UIKit
import AVFoundation

class KLQRCodeViewController: UIViewController {

    /// 底部视图
    @IBOutlet weak var customTabbar: UITabBar!
    
    /// 冲击波视图
     @IBOutlet weak var scanLineView: UIImageView!
    
    /// 冲击波顶部约束
    @IBOutlet weak var scanLineCons: NSLayoutConstraint!
    
    /// 扫描容器高度约束
    @IBOutlet weak var containerHeightCons: NSLayoutConstraint!
    
    @IBAction func closeButtonClick(sender: UIBarButtonItem) {
        dismissViewControllerAnimated(true, completion: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 1.设置底部视图默认选中第0个
        customTabbar.selectedItem = customTabbar.items![0]
        // 2.设置监听
        customTabbar.delegate = self
    }
    
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        // 1.开启冲击波动画
        startAnimation()
        // 2.开始扫描
        startScan()
    }
    
    // 显示我的名片
    @IBAction func showMyCard(sender: AnyObject) {
        print("Click My Cord")
//        let cardVC = KLQRCodeCardViewController()
//        navigationController?.pushViewController(cardVC, animated: true)
    }
    
    /**
     扫描二维码
     */
    private func startScan(){
        // 1.判断是否能够将输入添加到会话中
        if !session.canAddInput(deviceInput)
        {
            return
        }
        // 2.判断是否能够将输出添加到会话中
        if !session.canAddOutput(output)
        {
            return
        }
        // 3.将输入输出添加到会话
        session.addInput(deviceInput)
        session.addOutput(output)
        // 4.设置输出能够解析的数据类型
        output.metadataObjectTypes = output.availableMetadataObjectTypes
        // 5.设置输出对象的代理，只要解析成功就能通知代理
        output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        // 添加预览图层
        view.layer.insertSublayer(previewLayer, atIndex: 0)
        previewLayer.addSublayer(drawLayer)
        // 6.告诉session开始扫描
        session.startRunning()
    }
    
    private func startAnimation(){
        
        // 1.重新设置冲击波顶部约束
        // 一定要加上这一句, 否则会混乱
        scanLineCons.constant = -containerHeightCons.constant
        view.layoutIfNeeded()
        
        UIView.animateWithDuration(2.0) { () -> Void in
            // 0.设置动画重复次数
            UIView.setAnimationRepeatCount(MAXFLOAT)
            // 1.修改约束
            self.scanLineCons.constant = self.containerHeightCons.constant
            // 2.执行动画
            self.view.layoutIfNeeded()
        }
    }
    
    // MARK: -- 懒加载
    // 会话
    private lazy var session: AVCaptureSession = AVCaptureSession()
    
    //拿到输入设备
    private lazy var deviceInput: AVCaptureDeviceInput? = {
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        do{
            let input = try AVCaptureDeviceInput(device: device)
            return input
        }catch{
            print(error)
            return nil
        }
    }()
    
    // 拿到输出设备
    private lazy var output: AVCaptureMetadataOutput = AVCaptureMetadataOutput()
    
    // 创建预览图层
    private lazy var previewLayer: AVCaptureVideoPreviewLayer = {
        let layer = AVCaptureVideoPreviewLayer(session: self.session)
        layer.frame = UIScreen.mainScreen().bounds
        return layer
    }()
    
    // 创建用于绘制边线的图层
    private lazy var drawLayer: CALayer = {
        let layer = CALayer()
        layer.frame = UIScreen.mainScreen().bounds
        return layer
    }()
}

extension KLQRCodeViewController: AVCaptureMetadataOutputObjectsDelegate
{
    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!)
    {
        // 0.移除边线
        clearDrawLayer()
        
        // 1.获取解析的数据
        print(metadataObjects.last?.stringValue)
        
        // 2.获取二维码的位置
        print(metadataObjects.last)
        // 2.1转换坐标
        for object in metadataObjects
        {
            // 2.1.1当前获取的数据是否是机器可识别
            if object is AVMetadataMachineReadableCodeObject
            {
                // 2.1.2转换
                let codeObject = previewLayer.transformedMetadataObjectForMetadataObject(object as! AVMetadataObject) as! AVMetadataMachineReadableCodeObject
                print(codeObject)
                drawCorners(codeObject)
            }
        }
    }
    
    /**
     绘制图层
     */
    func drawCorners(codeObject: AVMetadataMachineReadableCodeObject)
    {
        if codeObject.corners.isEmpty
        {
            return
        }
        // 1.创建一个图层
        let layer = CAShapeLayer()
        layer.lineWidth = 4
        layer.strokeColor = UIColor.redColor().CGColor
        layer.fillColor = UIColor.clearColor().CGColor
        
        // 2.绘制图形
        layer.path = cornersPath(codeObject.corners)
    
        // 3.将创建好的图层添加到drawLayer上
        drawLayer.addSublayer(layer)
    }
    
    /**
     根据坐标数组生成路径
     
     :param: corners 坐标数组
     
     :returns: 路径
     */
    private func cornersPath(corners: NSArray) -> CGPath
    {
        // 3.1创建路径
        let path = UIBezierPath()
        var point = CGPointZero
        // 3.2移动到第一个点
        var index = 0
        // 取出第0个点
        CGPointMakeWithDictionaryRepresentation((corners[index] as! CFDictionaryRef), &point)
        path.moveToPoint(point)
        // 3.3设置其它点
        while index < corners.count
        {
            CGPointMakeWithDictionaryRepresentation((corners[index++] as! CFDictionaryRef), &point)
            path.addLineToPoint(point)
        }
        // 3.4关闭路径
        path.closePath()
        return path.CGPath
    }
    
    private func clearDrawLayer(){
        // 1.判断是否有边线
        if drawLayer.sublayers?.count == 0 || drawLayer.sublayers == nil
        {
            return
        }
        // 2.移除所有边线
        for layer in drawLayer.sublayers!
        {
            layer.removeFromSuperlayer()
        }
    }

}

extension KLQRCodeViewController: UITabBarDelegate
{
    func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
        // 1.修改高度
        print(item.tag)
        containerHeightCons.constant = item.tag == 1 ? 300 : 300 * 0.5
        
        // 2.停止动画
        self.scanLineView.layer.removeAllAnimations()
        
        // 3.重新开始动画
        startAnimation()
    }
}
